﻿using System;
using System.Collections.Generic;
using ComplexNumberLibrary;

namespace ComplexNumberPresentation
{
    public class Presenter
    {
        private const int LoggerToFileIndex = 0;
        private const int HtmlLoggerIndex = 1;
        public const String ImageBtnPressed = "i (Pressed)";
        public const String ImageBtnNotPressed = "i";

        private IView view;
        private ILogger logger;

        public Presenter(IView view)
        {
            this.view = view;
            this.view.Result = new ComplexNumber();
            this.view.CurrentOperation = Operation.None;
            this.view.ImaginaryFocused = false;
            this.view.LogText = "";

            view.OnAllClearClick += AllClearClick;
            view.OnClearClick += ClearClick;
            view.OnAddClick += AddClick;
            view.OnSubtractClick += SubtractClick;
            view.OnMultiplyClick += MultiplyClick;
            view.OnDivideClick += DivideClick;
            view.OnModulusClick += ModulusClick;
            view.OnOneClick += OneClick;
            view.OnTwoClick += TwoClick;
            view.OnThreeClick += ThreeClick;
            view.OnFourClick += FourClick;
            view.OnFiveClick += FiveClick;
            view.OnSixClick += SixClick;
            view.OnSevenClick += SevenClick;
            view.OnEightClick += EightClick;
            view.OnNineClick += NineClick;
            view.OnZeroClick += ZeroClick;
            view.OnImaginaryClick += ImaginaryClick;
            view.OnResultClick += ResultClick;
            view.OnShowLogClick += ShowLogClick;
            view.OnChooseLogClick += ChooseLogClick;
            view.OnSaveToFileClick += SaveToFileClick;

            logger = null;
        }

        public Presenter(IView view, ILogger logger)
        {
            this.view = view;
            this.view.Result = new ComplexNumber();
            this.view.CurrentOperation = Operation.None;
            this.view.ImaginaryFocused = false;
            this.view.LogText = "";

            view.OnAllClearClick += AllClearClick;
            view.OnClearClick += ClearClick;
            view.OnAddClick += AddClick;
            view.OnSubtractClick += SubtractClick;
            view.OnMultiplyClick += MultiplyClick;
            view.OnDivideClick += DivideClick;
            view.OnModulusClick += ModulusClick;
            view.OnOneClick += OneClick;
            view.OnTwoClick += TwoClick;
            view.OnThreeClick += ThreeClick;
            view.OnFourClick += FourClick;
            view.OnFiveClick += FiveClick;
            view.OnSixClick += SixClick;
            view.OnSevenClick += SevenClick;
            view.OnEightClick += EightClick;
            view.OnNineClick += NineClick;
            view.OnZeroClick += ZeroClick;
            view.OnImaginaryClick += ImaginaryClick;
            view.OnResultClick += ResultClick;
            view.OnShowLogClick += ShowLogClick;
            view.OnChooseLogClick += ChooseLogClick;
            view.OnSaveToFileClick += SaveToFileClick;

            this.logger = logger;
        }

        private void AllClearClick()
        {
            if (this.logger != null) logger.addLogMessage("All clear action(No current operation)");
            view.CurrentOperation = Operation.None;
            view.CurrentImaginary = 0;
            view.CurrentReal = 0;
            view.Result = new ComplexNumber();
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ClearClick()
        {
            if (this.logger != null) logger.addLogMessage("Clear action(No current operation)");
            view.CurrentImaginary = 0;
            view.CurrentReal = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void AddClick()
        {
            if (this.logger != null) logger.addLogMessage("Add action(Current operation = +)");
            view.CurrentOperation = Operation.Add;
            view.Result = view.Result + new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            view.CurrentReal = 0;
            view.CurrentImaginary = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void SubtractClick()
        {
            if (this.logger != null) logger.addLogMessage("Subtract action(Current operation = -)");
            view.CurrentOperation = Operation.Subtract;
            view.Result = view.Result + new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            view.CurrentReal = 0;
            view.CurrentImaginary = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void MultiplyClick()
        {
            if (this.logger != null) logger.addLogMessage("Multiply action(Current operation = *)");
            view.CurrentOperation = Operation.Multiply;
            view.Result = view.Result + new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            view.CurrentReal = 0;
            view.CurrentImaginary = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void DivideClick()
        {
            if (this.logger != null) logger.addLogMessage("Divide action(Current operation = /)");
            view.CurrentOperation = Operation.Divide;
            view.Result = view.Result + new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            view.CurrentReal = 0;
            view.CurrentImaginary = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ModulusClick()
        {
            if (this.logger != null) logger.addLogMessage("Modulus action(Current operation = |c|)");
            view.CurrentOperation = Operation.None;
            var num = new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            view.Result = new ComplexNumber();
            view.CurrentReal = num.Modulus();
            view.CurrentImaginary = 0;
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void OneClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 1 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 1;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 1 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 1;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void TwoClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 2 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 2;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 2 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 2;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ThreeClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 3 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 3;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 3 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 3;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void FourClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 4 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 4;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 4 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 4;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void FiveClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 5 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 5;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 5 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 5;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void SixClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 6 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 6;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 6 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 6;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void SevenClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 7 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 7;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 7 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 7;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void EightClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 8 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 8;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 8 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 8;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void NineClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 9 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10 + 9;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 9 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10 + 9;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ZeroClick()
        {
            if (view.ImaginaryFocused)
            {
                if (this.logger != null) logger.addLogMessage("Number 0 action(Added to Imaginary)");
                view.CurrentImaginary = view.CurrentImaginary * 10;
            }
            else
            {
                if (this.logger != null) logger.addLogMessage("Number 0 action(Added to Real)");
                view.CurrentReal = view.CurrentReal * 10;
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ImaginaryClick()
        {
            view.ImaginaryFocused = !view.ImaginaryFocused;
            view.ImaginaryText = view.ImaginaryFocused ? ImageBtnPressed : ImageBtnNotPressed;
            if (this.logger != null) logger.addLogMessage(view.ImaginaryFocused
                             ? "Image switch action. Switched to Imaginary"
                             : "Image switch action. Switched to Real");
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ResultClick()
        {
            var num = new ComplexNumber(view.CurrentReal, view.CurrentImaginary);
            switch (view.CurrentOperation)
            {
                case Operation.Add:
                    if (this.logger != null) logger.addLogMessage("Result action. Operation: C = " + view.Result + " + " + num);
                    view.Result = view.Result + num;
                    break;
                case Operation.Subtract:
                    if (this.logger != null) logger.addLogMessage("Result action. Operation: C = " + view.Result + " - " + num);
                    view.Result = view.Result - num;
                    break;
                case Operation.Multiply:
                    if (this.logger != null) logger.addLogMessage("Result action. Operation: C = (" + view.Result + ") * (" + num + ")");
                    view.Result = view.Result * num;
                    break;
                case Operation.Divide:
                    if (this.logger != null) logger.addLogMessage("Result action. Operation: C = (" + view.Result + ") / (" + num + ")");
                    view.Result = view.Result/num;
                    break;
                case Operation.None:
                    if (this.logger != null) logger.addLogMessage("Result action. Operation: Z = |" + num + "|");
                    view.Result = view.Result + num;
                    break;
            }
            if (this.logger != null) logger.addLogMessage("Result action. Result number C = " + view.Result + ". No current operation");
            view.CurrentOperation = Operation.None;
            view.CurrentReal = view.Result.Real;
            view.CurrentImaginary = view.Result.Image;
            view.Result = new ComplexNumber();
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private String GetLogText()
        {
            return (logger != null) ? logger.getLog() : "";
        }

        private void ShowLogClick()
        {
            view.LogVisible = !view.LogVisible;
            if (this.logger != null) logger.addLogMessage(view.LogVisible ? "Log Show action" : "Log Hide action");
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void ChooseLogClick(int logIndex)
        {
            view.LoggerIndex = logIndex;
            if (this.logger != null) logger.addLogMessage("Logger switched. Log Index = " + logIndex);
            var previousLog = new List<String>();
            if (logger != null)
            {
                previousLog.AddRange(logger.getLogMessages());
            }
            switch (logIndex)
            {
                case LoggerToFileIndex:
                    logger = view.getLoggerToFile();
                    break;
                case HtmlLoggerIndex:
                    logger = view.getHtmlLogger();
                    break;
            }
            logger.getLogMessages().AddRange(previousLog);
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }

        private void SaveToFileClick()
        {
            if (this.logger != null)
            {
                switch (view.LoggerIndex)
                {
                    case LoggerToFileIndex:
                        logger.addLogMessage("Log saved locally in LOG.txt file");
                        break;
                    case HtmlLoggerIndex:
                        logger.addLogMessage("Log saved locally in LOG.html file");
                        break;
                }
                logger.Write();
            }
            if (view.LogVisible)
            {
                view.LogText = GetLogText();
            }
        }
    }
}
